package org.dfl.plugin.dialogs;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import org.dfl.core.model.transitions.Transition;
import org.dfl.messages.Messages;
import org.dfl.plugin.editor.model.TransitionModelElement;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.layout.RowData;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;


/**
 * dialog to change transition properties
 * @author Piotr Wlodarczyk
 *
 */
public class TransitionPropertiesDialog extends BaseDialog  {
	private TransitionModelElement transitionModelElement;
	private Map<Control,String> errors = new HashMap<Control,String>();
	private Text ioDefinitionText;
	private boolean okButtonClicked = false;
	private Text nameField;
	private Text descrField;
	private Listener okListener;

	public TransitionPropertiesDialog(TransitionModelElement transitionModelElement){
		super();
		this.transitionModelElement = transitionModelElement;
	}

	public Transition getTransition() {
		return getTransitionModelElement().getTransition();
	}
	
	public TransitionModelElement getTransitionModelElement() {
		return transitionModelElement;
	}

	protected Shell getNewShell(){
		Shell shell = new Shell(getParent(), SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL);

		GridLayout dialogShellLayout = new GridLayout();
		dialogShellLayout.makeColumnsEqualWidth = true;
		shell.setLayout(dialogShellLayout);
		shell.layout();
		shell.pack();
		shell.setText(Messages.TransitionPropertiesDialog_title);
		
		// uncomment to deny closing this window
//		shell.addListener (SWT.Close, new Listener () {
//			public void handleEvent (Event event) {
//				event.doit = false;
//			}
//		});
		
		return shell;
	}

	@Override
	protected void init(final Shell dialogShell) {
		okListener = new Listener() {
			public void handleEvent(Event event) {
				Collection<String> err = errors.values();
				for(String msg : err){
					alert(msg);
					return;
				}
				finish();
				// check once again
				err = errors.values();
				for(String msg : err){
					alert(msg);
					return;
				}
				
				//if is ok
				try {
					okButtonClicked = true;
					dialogShell.dispose();
				} catch (Exception e) {
					DialogsManager.openErrorDialog(e);
				}
			}

			protected void alert(String text) {
				DialogsManager.openErrorDialog(text);
			}
		};
		
		// add IO definitions
		ioDefinitionText = addStringRow(dialogShell, true, true, Messages.TransitionPropertiesDialog_inputOutput, getTransition().getIODescription());
		
		// add name
		nameField = addStringRow(dialogShell, false, false, Messages.TransitionPropertiesDialog_name, getTransition().getName());
		setFieldErrorChecking(nameField, nameField.getText()==null || nameField.getText().equals(""), Messages.TransitionPropertiesDialog_errorEmptyName); //$NON-NLS-1$
		nameField.addModifyListener(new ModifyListener(){
			public void modifyText(ModifyEvent e) {
				setFieldErrorChecking(nameField, nameField.getText()==null || nameField.getText().equals(""), Messages.TransitionPropertiesDialog_errorEmptyName); //$NON-NLS-1$
			}});
		addEnterKeyListener(nameField);
		
		// add description 
		descrField = addStringRow(dialogShell, true, false, Messages.TransitionPropertiesDialog_description, getTransition().getDescription());

		addSpecificTransitionElements(dialogShell);
		addButtons(dialogShell);
		dialogShell.pack();
	}
	
	protected void addEnterKeyListener(Control control) {
		control.addListener(SWT.KeyDown, new Listener() {
		    public void handleEvent(Event event) {
		        if( event.keyCode == SWT.CR ) {
		        	okListener.handleEvent(event);
		        }
		    }
		});
	}

	protected void setFieldErrorChecking(Control field, boolean isError, String errorStr){
		if(isError){
			field.setBackground(Display.getDefault().getSystemColor(SWT.COLOR_RED));
			errors.put(field,errorStr);
		}else{
			field.setBackground(Display.getDefault().getSystemColor(SWT.COLOR_WHITE));
			errors.remove(field);
		}
	}
	
	private void addButtons(final Shell parent){
		Composite buttons = new Composite(parent, SWT.NONE);
		GridLayout buttonsLayout = new GridLayout();
		buttonsLayout.makeColumnsEqualWidth = true;
		GridData buttonsLData = new GridData();
		buttonsLData.heightHint = 40;
		buttonsLData.grabExcessHorizontalSpace = true;
		buttonsLData.horizontalAlignment = GridData.FILL;
		buttons.setLayoutData(buttonsLData);
		buttons.setLayout(buttonsLayout);
		{
			Composite buttonsCentered = new Composite(buttons, SWT.NONE);
			RowLayout buttonsCenteredLayout = new RowLayout(org.eclipse.swt.SWT.HORIZONTAL);
			GridData buttonsCenteredLData = new GridData();
			buttonsCenteredLData.widthHint = 198;
			buttonsCenteredLData.horizontalAlignment = GridData.CENTER;
			buttonsCenteredLData.grabExcessVerticalSpace = true;
			buttonsCenteredLData.grabExcessHorizontalSpace = true;
			buttonsCenteredLData.verticalAlignment = GridData.FILL;
			buttonsCentered.setLayoutData(buttonsCenteredLData);
			buttonsCentered.setLayout(buttonsCenteredLayout);
			{
				Button okButton = new Button(buttonsCentered, SWT.PUSH | SWT.CENTER);
				RowData okButtonLData = new RowData();
				okButtonLData.width = 88;
				okButtonLData.height = 23;
				okButton.setLayoutData(okButtonLData);
				okButton.setText(Messages.TransitionPropertiesDialog_ok);
				
				okButton.addListener(SWT.Selection, okListener);
			}
			{
				Button cancelButton = new Button(buttonsCentered, SWT.PUSH	| SWT.CENTER);
				RowData cancelButtonLData = new RowData();
				cancelButtonLData.width = 88;
				cancelButtonLData.height = 23;
				cancelButton.setLayoutData(cancelButtonLData);
				cancelButton.setText(Messages.TransitionPropertiesDialog_cancel);
				cancelButton.addListener(SWT.Selection, new Listener() {
					public void handleEvent(Event arg0) {
						parent.dispose();
					}
				});
			}
		}
	}
	
	protected void finish(){
		getTransition().setDescription(descrField.getText());
		getTransition().setName(nameField.getText());
	}
	
	
	/**
	 * add action for new transitions
	 * @param parent
	 */
	protected void addSpecificTransitionElements(final Shell parent){
		
	}

	public Text getIoDefinitionText() {
		return ioDefinitionText;
	}

	public boolean isOkButtonClicked() {
		return okButtonClicked;
	}
	
	public void refreshIODescription(){
		ioDefinitionText.setText(getTransition().getIODescription());
	}
}
